using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TPOJ.IDAL;
using TPOJ.Model;
using System.Data;

namespace TPOJ.LINQDAL
{
    class ContestDAO : IContestDAO
    {
        public IList<Contest> GetContests()
        {
            IList<Contest> result = new List<Contest>();

            using (var entities = new TPOJEntities())
            {
                var query = from c in entities.Contests
                            orderby c.UniqueID descending
                            select c;

                foreach (var p in query)
                {
                    result.Add(p);
                }
            }
            return result;
        }

        public Contest GetContest(int id)
        {
            Contest result;

            using (var entities = new TPOJEntities())
            {
                var query = entities.Contests.Include("Problems").Where(c => c.UniqueID == id);
                result = query.First();
            }

            return result;
        }

        public IList<Standing> GetContestStanding(int contestId)
        {
            var result = new List<Standing>();

            using (var entities = new TPOJEntities())
            {
                var query = from s in entities.Standings.Include("StandingCells")
                            where s.ContestId == contestId
                            select s;
                foreach (var s in query)
                {
                    result.Add(s);
                }
            }

            return result;
        }

        public IList<Contest> GetCurrentContests()
        {
            IList<Contest> result;

            using (var entities = new TPOJEntities())
            {
                var query = from c in entities.Contests.Include("Problems")
                            where c.StartTime <= DateTime.Now && DateTime.Now < c.EndTime
                            select c;
                result = query.ToList();
            }
            return result;
        }


        public Standing FindContestStanding(int contestId, int accountId)
        {
            Standing result;

            using (var entities = new TPOJEntities())
            {
                var query = from s in entities.Standings
                            where s.ContestId == contestId && s.AccountId == accountId
                            select s;
                result = query.FirstOrDefault();
            }
            return result;
        }


        public Standing AddContestStanding(int contestId, int accountId)
        {
            Standing standing = new Standing { ContestId = contestId, AccountId = accountId };

            using (var entities = new TPOJEntities())
            {
                var queryContest = from c in entities.Contests
                                   where c.UniqueID == contestId
                                   select c;
                standing.Contest = queryContest.First();

                entities.Standings.AddObject(standing);

                try
                {
                    entities.SaveChanges();
                }
                catch (OptimisticConcurrencyException)
                {
                    entities.Refresh(System.Data.Objects.RefreshMode.ClientWins, standing);
                    entities.SaveChanges();
                }
            }

            return standing;
        }


        public StandingCell FindContestStandingCell(int standingId, int id)
        {
            StandingCell result;

            using (var entities = new TPOJEntities())
            {
                var query = from sc in entities.StandingCells
                            where sc.StandingId == standingId && sc.Id == id
                            select sc;
                result = query.FirstOrDefault();
            }
            return result;
        }

        public StandingCell AddContestStandingCell(int standingId, int cellId)
        {
            StandingCell cell = new StandingCell { StandingId = standingId, Id = cellId };

            using (var entities = new TPOJEntities())
            {
                var queryStanding = from s in entities.Standings
                                    where s.UniqueId == standingId
                                    select s;
                var standing = queryStanding.First();

                cell.Standing = standing;

                entities.StandingCells.AddObject(cell);

                try
                {
                    entities.SaveChanges();
                }
                catch (OptimisticConcurrencyException)
                {
                    entities.Refresh(System.Data.Objects.RefreshMode.ClientWins, cell);
                    entities.SaveChanges();
                }
            }

            return cell;
        }

        public StandingCell EditContestStandingCell(int id, int standingId, int time, int waSubmits, int submits)
        {
            StandingCell cell;
            using (var entities = new TPOJEntities())
            {
                var query = from sc in entities.StandingCells
                            where sc.StandingId == standingId && sc.Id == id
                            select sc;
                cell = query.FirstOrDefault();
                cell.Time = time;
                cell.WA_Submits = waSubmits;
                cell.Submits = submits;
                
                try
                {
                    entities.SaveChanges();
                }
                catch (OptimisticConcurrencyException)
                {
                    entities.Refresh(System.Data.Objects.RefreshMode.ClientWins, cell);
                    entities.SaveChanges();
                }
            }
            return cell;
        }


        public void RefreshStanding(int standingId)
        {
            Standing standing;

            using (var entities = new TPOJEntities())
            {
                var query = from s in entities.Standings.Include("StandingCells")
                            where s.UniqueId == standingId
                            select s;
                standing = query.First();
                var acCells = standing.StandingCells.Where(sc => sc.Time > 0);
                int accepts = acCells.Count();
                int? time = acCells.Sum(sc=>sc.Time)+ acCells.Sum(sc=>sc.WA_Submits)*20;
                standing.Accepts = accepts;
                standing.Time =time;

                try
                {
                    entities.SaveChanges();
                }
                catch (OptimisticConcurrencyException)
                {
                    entities.Refresh(System.Data.Objects.RefreshMode.ClientWins, standing);
                    entities.SaveChanges();
                }
            }
        }


        public void Create(Contest contest)
        {
            using (var entities = new TPOJEntities())
            {
                entities.AddToContests(contest);
                entities.SaveChanges();
            }
        }


        public void AddContestProblem(int cid, int pid)
        {
            using (var entities = new TPOJEntities())
            {
                var queryContest = from c in entities.Contests
                                   where c.UniqueID == cid
                                   select c;
                var contest = queryContest.First();

                var queryProblem = from p in entities.Problems
                                   where p.UniqueID == pid
                                   select p;
                var problem = queryProblem.First();

                contest.Problems.Add(problem);

                try
                {
                    entities.SaveChanges();
                }
                catch (OptimisticConcurrencyException)
                {
                    entities.Refresh(System.Data.Objects.RefreshMode.ClientWins, contest);
                    entities.SaveChanges();
                }
            }
        }


        public void DeleteContestProblem(int cid, int pid)
        {
            using (var entities = new TPOJEntities())
            {
                var queryContest = from c in entities.Contests.Include("Problems")
                                   where c.UniqueID == cid
                                   select c;
                var contest = queryContest.First();

                var queryProblem = from p in contest.Problems
                                   where p.UniqueID == pid
                                   select p;
                var problem = queryProblem.First();

                contest.Problems.Remove(problem);

                try
                {
                    entities.SaveChanges();
                }
                catch (OptimisticConcurrencyException)
                {
                    entities.Refresh(System.Data.Objects.RefreshMode.ClientWins, contest);
                    entities.SaveChanges();
                }
            }
        }


        public Contest Edit(Contest contest)
        {
            Contest result;
            using (var entities = new TPOJEntities())
            {
                var query = from c in entities.Contests
                            where c.UniqueID == contest.UniqueID
                            select c;
                result = query.FirstOrDefault();

                result.Title = contest.Title;
                result.Description = contest.Description;
                result.StartTime = contest.StartTime;
                result.EndTime = contest.EndTime;
                result.IsPrivate = contest.IsPrivate;
                result.IsBlocked = contest.IsBlocked;

                try
                {
                    entities.SaveChanges();
                }
                catch (OptimisticConcurrencyException)
                {
                    entities.Refresh(System.Data.Objects.RefreshMode.ClientWins, result);
                    entities.SaveChanges();
                }
            }
            return result;
        }
    }
}
